{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 设计基函数(basis function) 以及数据读取"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "def identity_basis(x):\n",
    "    ret = np.expand_dims(x, axis=1)\n",
    "    return ret\n",
    "\n",
    "def multinomial_basis(x, feature_num=10):\n",
    "    x = np.expand_dims(x, axis=1) # shape(N, 1)\n",
    "    feat = [x]\n",
    "    for i in range(2, feature_num+1):\n",
    "        feat.append(x**i)\n",
    "    ret = np.concatenate(feat, axis=1)\n",
    "    return ret\n",
    "\n",
    "def gaussian_basis(x, feature_num=10):\n",
    "    centers = np.linspace(0, 25, feature_num)\n",
    "    width = 1.0 * (centers[1] - centers[0])\n",
    "    x = np.expand_dims(x, axis=1)\n",
    "    x = np.concatenate([x]*feature_num, axis=1)\n",
    "    \n",
    "    out = (x-centers)/width\n",
    "    ret = np.exp(-0.5 * out ** 2)\n",
    "    return ret\n",
    "\n",
    "def load_data(filename, basis_func=gaussian_basis):\n",
    "    \"\"\"载入数据。\"\"\"\n",
    "    xys = []\n",
    "    with open(filename, 'r') as f:\n",
    "        for line in f:\n",
    "            xys.append(map(float, line.strip().split()))\n",
    "        xs, ys = zip(*xys)\n",
    "        xs, ys = np.asarray(xs), np.asarray(ys)\n",
    "        \n",
    "        o_x, o_y = xs, ys\n",
    "        phi0 = np.expand_dims(np.ones_like(xs), axis=1)\n",
    "        phi1 = basis_func(xs)\n",
    "        xs = np.concatenate([phi0, phi1], axis=1)\n",
    "        return (np.float32(xs), np.float32(ys)), (o_x, o_y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "from tensorflow.keras import optimizers, layers, Model\n",
    "\n",
    "class linearModel(Model):\n",
    "    def __init__(self, ndim):\n",
    "        super(linearModel, self).__init__()\n",
    "        self.w = tf.Variable(\n",
    "            shape=[ndim, 1], \n",
    "            initial_value=tf.random.uniform(\n",
    "                [ndim,1], minval=-0.1, maxval=0.1, dtype=tf.float32))\n",
    "        \n",
    "    @tf.function\n",
    "    def call(self, x):\n",
    "        y = tf.squeeze(tf.matmul(x, self.w), axis=1)\n",
    "        return y\n",
    "\n",
    "(xs, ys), (o_x, o_y) = load_data('train.txt')        \n",
    "ndim = xs.shape[1]\n",
    "\n",
    "model = linearModel(ndim=ndim)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练以及评估"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "optimizer = optimizers.Adam(0.1)\n",
    "@tf.function\n",
    "def train_one_step(model, xs, ys):\n",
    "    with tf.GradientTape() as tape:\n",
    "        y_preds = model(xs)\n",
    "        loss = tf.reduce_mean(tf.sqrt(1e-12+(ys-y_preds)**2))\n",
    "    grads = tape.gradient(loss, model.w)\n",
    "    optimizer.apply_gradients([(grads, model.w)])\n",
    "    return loss\n",
    "\n",
    "@tf.function\n",
    "def predict(model, xs):\n",
    "    y_preds = model(xs)\n",
    "    return y_preds\n",
    "\n",
    "def evaluate(ys, ys_pred):\n",
    "    \"\"\"评估模型。\"\"\"\n",
    "    std = np.sqrt(np.mean(np.abs(ys - ys_pred) ** 2))\n",
    "    return std"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss is 1.641\n",
      "loss is 1.366\n",
      "loss is 1.172\n",
      "loss is 0.9912\n",
      "loss is 0.8082\n",
      "loss is 0.6387\n",
      "loss is 0.5018\n",
      "loss is 0.412\n",
      "loss is 0.3852\n",
      "loss is 0.3598\n",
      "训练集预测值与真实值的标准差：0.6\n",
      "训练集预测值与真实值的标准差：0.8\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "for i in range(1000):\n",
    "    loss = train_one_step(model, xs, ys)\n",
    "    if i % 100 == 1:\n",
    "        print(f'loss is {loss:.4}')\n",
    "        \n",
    "        \n",
    "y_preds = predict(model, xs)\n",
    "std = evaluate(ys, y_preds)\n",
    "print('训练集预测值与真实值的标准差：{:.1f}'.format(std))\n",
    "\n",
    "(xs_test, ys_test), (o_x_test, o_y_test) = load_data('test.txt')\n",
    "\n",
    "y_test_preds = predict(model, xs_test)\n",
    "std = evaluate(ys_test, y_test_preds)\n",
    "print('训练集预测值与真实值的标准差：{:.1f}'.format(std))\n",
    "\n",
    "plt.plot(o_x, o_y, 'ro', markersize=3)\n",
    "plt.plot(o_x_test, y_test_preds, 'k')\n",
    "plt.xlabel('x')\n",
    "plt.ylabel('y')\n",
    "plt.title('Linear Regression')\n",
    "plt.legend(['train', 'test', 'pred'])\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
